package cn.ztuo.bitrade.service;

import cn.ztuo.bitrade.constant.TransactionType;
import cn.ztuo.bitrade.dao.EarningsBuyRecordDao;
import cn.ztuo.bitrade.dao.EarningsTreasureDao;
import cn.ztuo.bitrade.dao.MemberTransactionDao;
import cn.ztuo.bitrade.dao.MemberWalletDao;
import cn.ztuo.bitrade.entity.*;
import cn.ztuo.bitrade.service.Base.BaseService;
import cn.ztuo.bitrade.util.BigDecimalUtils;
import cn.ztuo.bitrade.util.MessageResult;
import cn.ztuo.bitrade.util.PredicateUtils;
import cn.ztuo.bitrade.util.RedisUtil;
import cn.ztuo.bitrade.vo.EarningsBuyRecordVO;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.BooleanExpression;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;

import static cn.ztuo.bitrade.util.MessageResult.success;

/**
 * @author: Xiazt
 * @date: 2020-04-09 10:30
 */
@Service
public class EarningsBuyRecordService extends BaseService {

    @Autowired
    private EarningsBuyRecordDao earningsBuyRecordDao;

    @Autowired
    private MemberWalletDao memberWalletDao;

    @Autowired
    private EarningsTreasureDao earningsTreasureDao;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private MemberTransactionDao memberTransactionDao;


    public EarningsBuyRecord getById(Long id) {
        return earningsBuyRecordDao.findById(id);
    }

    public EarningsBuyRecord inster(EarningsBuyRecord earningsBuyRecord) {
        return earningsBuyRecordDao.save(earningsBuyRecord);
    }

    @Transactional
    public MessageResult buyEarningsTreasure(EarningsTreasure earningsTreasure, Member member, MemberWallet memberWallet, BigDecimal aomunt) {
        // ------------------------------- 保存购买记录 ---------------------------------------
        EarningsBuyRecord earningsBuyRecord = new EarningsBuyRecord();
        // 购买人
        earningsBuyRecord.setMember(member);
        // 收益宝id
        earningsBuyRecord.setEarnings(earningsTreasure);
        // 数量
        earningsBuyRecord.setBuyAmount(aomunt);
        // 计算获取收益时间
        LocalDateTime earningsDate = earningsBuyRecord.getBuyDate().plusDays(earningsTreasure.getPeriod());
        earningsBuyRecord.setEarningsDate(earningsDate);

        // 计算收益
        // 将利率转为小数
        BigDecimal interestRate = BigDecimalUtils.div(earningsTreasure.getInterestRate(), new BigDecimal(100));
        // 本金 * 利率（年） = 年收益
        BigDecimal yearEarnings = BigDecimalUtils.mul(aomunt, interestRate);
        // 年收益 / 365 = 天收益
        BigDecimal dayEarnings = BigDecimalUtils.div(yearEarnings, new BigDecimal(365));
        // 天收益 * 周期（天） = 周期收益
        BigDecimal expectedEarnings = BigDecimalUtils.mul(dayEarnings, earningsTreasure.getPeriod());
        earningsBuyRecord.setExpectedEarnings(expectedEarnings);
        // 状态
        earningsBuyRecord.setStatus(0);
        EarningsBuyRecord save = earningsBuyRecordDao.save(earningsBuyRecord);

        // ------------------------------- 扣除账户余额 ---------------------------------------
        BigDecimal subBalance = BigDecimalUtils.sub(memberWallet.getBalance(), aomunt);
        memberWallet.setBalance(subBalance);
        memberWalletDao.save(memberWallet);

        // 资产流水
        MemberTransaction memberTransaction = new MemberTransaction();
        memberTransaction.setMemberId(member.getId());
        memberTransaction.setSymbol(memberWallet.getCoin().getUnit());
        memberTransaction.setCreateTime(new Date());
        memberTransaction.setAmount(aomunt.negate());
        memberTransaction.setType(TransactionType.EARNINGS_TREASURE_BUY);
        memberTransactionDao.save(memberTransaction);

        // ------------------------------- 修改收益宝数据 ---------------------------------------
        // 修改该收益宝卖出数量
        BigDecimal soldAomunt = BigDecimalUtils.add(earningsTreasure.getSoldAomunt(), aomunt);
        earningsTreasure.setSoldAomunt(soldAomunt);
        // 如果已卖出数量大于等于总量，修改状态为已结束，并删除redis数据
        if (soldAomunt.compareTo(earningsTreasure.getTotalAomunt()) >= 0) {
            earningsTreasure.setStatus(0);
            if (redisUtil.hasKey("earningsTreasure:end:" + earningsTreasure.getId())) {
                redisUtil.delete("earningsTreasure:end:" + earningsTreasure.getId());
            }
        }
        earningsTreasureDao.save(earningsTreasure);

        // ------------------------------- 将获取收益时间存入redis ---------------------------------------
        long earningsSeconds = ChronoUnit.SECONDS.between(LocalDateTime.now(), earningsBuyRecord.getEarningsDate());
        redisUtil.set("earningsBuyRecord:earnings:" + save.getId(), save.getId(), earningsSeconds);
        return success("购买成功");
    }

    public Page<EarningsBuyRecord> getByPage(EarningsBuyRecordVO earningsBuyRecordVO) {
        ArrayList<BooleanExpression> booleanExpressions = new ArrayList<>();

        // 查询条件
        if (earningsBuyRecordVO.getMemberId() != null){
            booleanExpressions.add(QEarningsBuyRecord.earningsBuyRecord.member.id.eq(earningsBuyRecordVO.getMemberId()));
        }
        if (StringUtils.isNotEmpty(earningsBuyRecordVO.getTitle())) {
            booleanExpressions.add(QEarningsBuyRecord.earningsBuyRecord.earnings.title.like("%" + earningsBuyRecordVO.getTitle() + "%"));
        }
        if (StringUtils.isNotEmpty(earningsBuyRecordVO.getCoin())) {
            booleanExpressions.add(QEarningsBuyRecord.earningsBuyRecord.earnings.coin.name.like("%" + earningsBuyRecordVO.getCoin() + "%"));
        }
        if (StringUtils.isNotEmpty(earningsBuyRecordVO.getUserName())) {
            booleanExpressions.add(QEarningsBuyRecord.earningsBuyRecord.member.username.like("%" + earningsBuyRecordVO.getUserName() + "%"));
        }
        if (StringUtils.isNotEmpty(earningsBuyRecordVO.getUserMobile())) {
            booleanExpressions.add(QEarningsBuyRecord.earningsBuyRecord.member.mobilePhone.like("%" + earningsBuyRecordVO.getUserMobile() + "%"));
        }
        if (earningsBuyRecordVO.getStatus() != null) {
            booleanExpressions.add(QEarningsBuyRecord.earningsBuyRecord.status.eq(earningsBuyRecordVO.getStatus()));
        }
        Predicate predicate = PredicateUtils.getPredicate(booleanExpressions);
        // 排序条件
        Sort sort = new Sort(Sort.Direction.DESC, "buyDate");
        Pageable pageable = new PageRequest(earningsBuyRecordVO.getPageNum() - 1, earningsBuyRecordVO.getPageSize(), sort);
        return earningsBuyRecordDao.findAll(predicate, pageable);
    }
}
